// 
// Bachelor of Software Engineering
// Media Design School
// Auckland
// New Zealand
//
// (c) 2005 - 2014 Media Design School
//
// File Name	: CannonComponent.cpp
// Desrciption	: CCannonComponent implementation file.
// Author		: Hayden Asplet.
// Mail			: hayden.asplet@mediadesignschool.com
//

// PCH
#include "SpaceInvadersStd.h"

// Library Includes

// This Include
#include "CannonComponent.h"

// Local Includes

CCannonComponent::CCannonComponent()
	:m_iScore(0),
	m_iLives(0),
	m_iAmmo(0),
	m_fInitialBulletVelocity(0.0f),
	m_fBulletAcceleration(0.0f),
	m_bIsInvulnerable(false)
{

}

CCannonComponent::~CCannonComponent()
{

}

bool CCannonComponent::VInitialize(TiXmlElement* _pXmlData)
{
	TiXmlElement* pLives = _pXmlData->FirstChildElement("StartingLives");

	if(pLives) {
		// Get the starting lives from the xml.
		std::string value = pLives->FirstChild()->Value();

		// Convert to integer.
		m_iLives = atoi(value.c_str());
	}
	else {
	// No lives element found in xml.
		// An alien component needs a worth value.
		return false;
	}

	TiXmlElement* pAmmo = _pXmlData->FirstChildElement("StartingAmmo");

	if(pAmmo) {
		// Get the starting lives from the xml.
		std::string value = pAmmo->FirstChild()->Value();

		// Convert to integer.
		m_iAmmo = atoi(value.c_str());
	}
	else {
	// No ammo element found in xml.
		// An alien component needs a worth value.
		return false;
	}

	TiXmlElement* pInitialBulletVelocity = _pXmlData->FirstChildElement("InitialBulletVelocity");

	if(pInitialBulletVelocity) {
		// Get the bullet velocity amount from the xml.
		std::string value = pInitialBulletVelocity->FirstChild()->Value();

		// Convert to integer.
		m_fInitialBulletVelocity = static_cast<float>(atof(value.c_str()));
	}
	else {
	// No initial bullet velocity found in xml.
		// A laser cannon component needs an initial bullet velocity.
		return false;
	}

	TiXmlElement* pBulletAcceleration = _pXmlData->FirstChildElement("BulletAcceleration");

	if(pBulletAcceleration) {
		// Get the bullet velocity amount from the xml.
		std::string value = pBulletAcceleration->FirstChild()->Value();

		// Convert to integer.
		m_fBulletAcceleration = static_cast<float>(atof(value.c_str()));
	}
	else {
	// No initial bullet velocity found in xml.
		// An alien component needs an initial bullet velocity.
		m_fBulletAcceleration = 0.0f;
	}

	// Success.
	return true;
}

void CCannonComponent::VPostInitialize()
{
	// Nothing to post initialize.
}

void CCannonComponent::VUpdate(float _fDeltaTime)
{
	// Nothing to update.
}

void CCannonComponent::FireBullet()
{
	if(m_iAmmo > 0) {
		// Create a bullet.
		CGameObject* pBullet = g_pApp->m_pGame->CreateGameObject("GameObjects\\Bullet.xml");

		if(pBullet) {
		// Did the bullet create successfully?
			// Obtain the required components to fire a bullet.
			shared_ptr<CPositionComponent> pBulletPosition = pBullet->GetComponent<CPositionComponent>();
			shared_ptr<CPhysicsComponent> pBulletPhysics = pBullet->GetComponent<CPhysicsComponent>();
			shared_ptr<CPhysicsComponent> pCannonPhysics = m_pOwner->GetComponent<CPhysicsComponent>();

			if(pBulletPosition && pBulletPhysics && pCannonPhysics) {
			// Do all these components exist?
				CRect cannonWorldBox = pCannonPhysics->GetWorldBoundingBox();
				CRect bulletBox = pBulletPhysics->GetBoundingBox();

				// Set the bullets position to be in the centre of the cannon and just above it.
				CPoint bulletPosition(cannonWorldBox.m_iX + cannonWorldBox.m_iWidth / 2, cannonWorldBox.m_iY - bulletBox.m_iHeight);
				pBulletPosition->SetPosition(bulletPosition);

				shared_ptr<CEvtDataMoveObject> pEvent(new CEvtDataMoveObject(pBullet->GetId(), false, 0, m_fInitialBulletVelocity));
				CEventManager::GetInstance()->QueueEvent(pEvent);

				shared_ptr<CEvtDataMoveObject> pEvent2(new CEvtDataMoveObject(pBullet->GetId(), false, m_fBulletAcceleration));
				CEventManager::GetInstance()->QueueEvent(pEvent2);
			}

			// Decrement ammo amount.
			--m_iAmmo;
		}
		else {
		// Bullet couldn't be created successfully.
			std::cerr << "WARNING: Bullet not created when firing one from a alien." << std::endl;
		}
	}
	else {
		// Can't fire a bullet if you don't have any ammo.
	}
}

void CCannonComponent::AddToScore(int _iAmount)
{
	m_iScore += _iAmount;
}

void CCannonComponent::LoseLife()
{
	if(!m_bIsInvulnerable) {
		--m_iLives;
	}
	else {
	}
}

void CCannonComponent::AddToAmmo()
{
	++m_iAmmo;
}

void CCannonComponent::SetInvulnerability(bool _bIsInvulnerable)
{
	m_bIsInvulnerable = _bIsInvulnerable;
}

void CCannonComponent::SetAmmo(int _iAmmo)
{
	m_iAmmo = _iAmmo;
}

void CCannonComponent::SetScore(int _iScore) 
{
	m_iScore = _iScore;
}

void CCannonComponent::SetLives(int _iLives)
{
	m_iLives = _iLives;
}

int CCannonComponent::GetScore() const
{
	return m_iScore;
}

int CCannonComponent::GetLives() const
{
	return m_iLives;
}

int CCannonComponent::GetAmmoAmount() const
{
	return m_iAmmo;
}

TStrongObjectComponentPtr CreateCannonComponent()
{
	return TStrongObjectComponentPtr(new CCannonComponent());
}